﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using XDL.Framework.Weapons;
using XDL.Framework;
using XDL.Framework.Messaging;

namespace JumpNFight.Simulation
{
    class Player : 
        EntityBase
    {
        public const int RegisterHitEvent = 2001;
        public const int RegisterKillEvent = 2002;

        public bool HasBeenStarted = false;

        public int Score = 0;

        // Negative Y is "up"
        static Vector2 g_jumpForce = new Vector2(0, -650);

        Moveable m_moveable;
        public override Moveable Moveable
        {
            get
            {
                return m_moveable;
            }
        }

        Sliceable m_sliceable;
        public override Sliceable Sliceable
        {
            get 
            {
                return m_sliceable; 
            }
        }


        public Vector2 Position
        {
            get
            {
                return m_moveable.Position;
            }
        }
        public int Width
        {
            get
            {
                return m_moveable.Width;
            }
        }
        public int Height
        {
            get
            {
                return m_moveable.Height;
            }
        }

        /// <summary>
        /// Gets or sets the active weapon
        /// </summary>
        public IWeapon Weapon
        {
            get
            { 
                return m_weapon; 
            }
            set
            {
                m_weapon = value;
            }
        }

        IWeapon m_weapon;

        public Player(Game game, PlayerIndex index):
            base((int)index, game)
        {
            IsAlive = false;
            IsActive = false;
            m_moveable = new Moveable(ID);
            m_moveable.Mass = 200;
            m_moveable.MaxSpeed = 220;

            m_sliceable = new Sliceable(this);
        }

        public void Jump()
        {
            if (m_moveable.TouchingGround)
            {
                m_moveable.Velocity += g_jumpForce;
            }
        }

        TimeSpan m_lastFireTime = TimeSpan.Zero;
        public TimeSpan LastFireTime
        {
            get
            {
                return m_lastFireTime;
            }
        }

        public void Fire(GameTime gameTime)
        {       
            bool reloadTimeElapsed = (gameTime.TotalGameTime - m_lastFireTime).TotalSeconds > m_weapon.Settings.ReloadTime;
            if (reloadTimeElapsed)
            {
                m_lastFireTime = gameTime.TotalGameTime;
                m_weapon.Fire((int)ID, new Vector3(Position.X + (IsRunningRight ? Width : -Width), Position.Y, 0), new Vector3(IsRunningRight ? 1 : -1, 0, 0));
                m_moveable.Push(IsRunningRight? -m_weapon.Settings.RecoilForce:m_weapon.Settings.RecoilForce);                
            }
        }

        public void Move(Vector2 direction)
        {
            if (IsAlive)
            {
                if (direction.X > 0)
                    IsRunningRight = true;
                else if (direction.X < 0)
                    IsRunningRight = false;

                m_moveable.Move(direction);
            }
        }

        public override bool ProcessEvent(GameTime gameTime, int msgId, EventArgs e)
        {
            switch (msgId)
            { 
                case Player.RegisterHitEvent:
                    Score += 50;
                    break;

                case Player.RegisterKillEvent:
                    Score += 100;
                    break;

                case Crate.HitEvent:
                    // "acquire" new weapon
                    m_weapon = ((CrateHitEventArgs)e).Weapon;
                    // reset last fired counter (set it to an arbitrary far far away but still avoid timespan underflow!!)
                    m_lastFireTime = TimeSpan.Zero;
                    break;

                case Weapons.FlameThrowerWeaponSystem.FryEvent:
                    // simulate "it burns" by jumping!
                    Weapons.FlameWeaponHitEventArgs args = (Weapons.FlameWeaponHitEventArgs)e;
                    Moveable.Push(new Vector2(Rnd.Next(-10,10), -200));
                    break;

                default:
                    return base.ProcessEvent(gameTime, msgId, e);
            }
            return true;
        }

        /// <summary>
        /// Internal help to kill this entity.
        /// </summary>
        protected override void Kill(GameTime gameTime, Vector2 velocity)
        {
            base.Kill(gameTime, velocity);
            Moveable.Velocity = new Vector2(Rnd.Next(-32, 32), -Rnd.Next(400, 450));
        }

        public void Start()
        {
            Sliceable.Reset();
            // register the object in the event system
            GameServices.EventDispatcher.RegisterClient(this);
        }

        public void Stop()
        {
            Moveable.TouchingGround = false;
            Moveable.Drag = 0;
            IsAlive = false;
            IsActive = false;
            HasBeenStarted = false;
        }
    }
}
